using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Verse;
using Verse.AI;

namespace RimWorld
{
abstract class IncidentWorker_ShipPartCrash : IncidentWorker
{
    //Constants
    private const float ShipPointsFactor = 0.9f;
    private const int IncidentMinimumPoints = 300; //One centipede

    //Properties
    protected virtual int CountToSpawn { get { return 1; } }

	protected override bool CanFireNowSub(IIncidentTarget target)
	{
		var map = (Map)target;

        if (map.listerThings.ThingsOfDef(def.shipPart).Count > 0)
            return false;

        return true;
    }

    public override bool TryExecute(IncidentParms parms)
	{
		var map = (Map)parms.target;

        int spawnedCount = 0;
        int countToSpawn = CountToSpawn;
        IntVec3 lastSpawnedLoc = IntVec3.Invalid;

        for (int i = 0; i < countToSpawn; ++i)
        {
            Predicate<IntVec3> validator = c =>
            {
                if (c.Fogged(map))
                    return false;

                foreach( var subCell in GenAdj.CellsOccupiedBy(c, Rot4.North, def.shipPart.size))
                {
                    if (!subCell.Standable(map))
                        return false;

                    if (map.roofGrid.Roofed(subCell))
                        return false;
                }

                if (!map.reachability.CanReachColony(c))
                    return false;

                return true;
            };


            IntVec3 center;
            if (!CellFinderLoose.TryFindRandomNotEdgeCellWith(14, validator, map, out center))
                break;

            // Make the crash explosion
            GenExplosion.DoExplosion(center, map, 3f, DamageDefOf.Flame, null);

            // Spawn the ship part
            Building_CrashedShipPart shipPart = (Building_CrashedShipPart)GenSpawn.Spawn(def.shipPart, center, map);
            shipPart.SetFaction(Faction.OfMechanoids);
            shipPart.pointsLeft = parms.points * ShipPointsFactor;
            if (shipPart.pointsLeft < IncidentMinimumPoints)
                shipPart.pointsLeft = IncidentMinimumPoints;

            ++spawnedCount;
            lastSpawnedLoc = center;
        }

        if (spawnedCount > 0)
        {
			if( map == Find.VisibleMap )
				Find.CameraDriver.shaker.DoShake(1.0f);

            //Make letter
			Find.LetterStack.ReceiveLetter(def.letterLabel, def.letterText, def.letterType, new TargetInfo(lastSpawnedLoc, map));
        }

        return spawnedCount > 0;
    }
}
}
